﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IPlugin;
using System.Threading;
using System.IO;
using System.Web;

namespace Plugin
{
    public class Plugin : IPlugin.IPlugin
    {
        private string htmlFileName = "index.html";
        private StringBuilder stringBuilder;
        public string Name
        {
            get { return "GetFile"; }
        }
        public string Version
        {
            get { return "1.0 Beta"; }
        }

        public Plugin()
        {
            try
            {
                if (!Directory.Exists("Webspace"))
                {
                    Directory.CreateDirectory("Webspace");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: Server muss beendet werden.\nDetail: " + ex.Message);
                Console.Read();
                Environment.Exit(0);
            }
            if (!File.Exists("Plugins\\" + Name + '\\' + htmlFileName))
            {
                Console.WriteLine("Error: Filebrowser-Plugin\n" +
                    "Im Verzeichnis 'Plugins\\" + Name + "' wurde keine HTML-Datei gefunden.\n" +
                "Bitte stellen sie eine HTML-Datei mit dem Dateinamen '" + htmlFileName + "' bereit.\nServer muss beendet werden.");
                Console.Read();
                Environment.Exit(0);
            }

            FileStream fs = null;
            StreamReader sr = null;
            try
            {
                fs = File.OpenRead("Plugins\\" + Name + '\\' + htmlFileName);
                sr = new StreamReader(fs);
                stringBuilder = new StringBuilder("");
                while (!sr.EndOfStream)
                {
                    stringBuilder.Append(sr.ReadLine());
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: Filebrowser-Plugin\nDetail: " + ex.Message);
                Console.Read();
                Environment.Exit(0);
            }
            finally
            {
                if (fs != null)
                    fs.Close();
                if (sr != null)
                    sr.Close();
            }
        }
        public Response ExecutePlugin(Request req)
        {
            string decodedPath = HttpUtility.UrlDecode(req.ReqUrl.Path); //z.B. %20 umwandeln zu ' '
            if(!decodedPath.Equals("/"))
                decodedPath = decodedPath.TrimEnd('/');
            string[] separatedBlocks = decodedPath.Split(new char[] {'/'}, 3);

            if (separatedBlocks[1].Equals("GetFile"))
            {
                if (separatedBlocks.Length <= 2)
                {
                    //Es wurde nur /GetFile eingegeben. Ist das selbe wie nur /
                    separatedBlocks[1] = "";
                }
                else
                {
                    //Nach GetFile befinden sich noch weitere Elemente. Daher nur GetFile Element aus Url entfernen
                    separatedBlocks[1] = separatedBlocks[2];
                    separatedBlocks[2] = null;
                }
            } 
            
            if (separatedBlocks[1].Equals(""))
            {
                //Root Webspace-Verzeichnis anzeigen
                if (Directory.Exists("Webspace"))
                {
                    string htmlOutput = stringBuilder.ToString();
                    string htmlText = "<tr><th>Name</th><th>Type</th>";

                    int i = 0;
                    string[] dirs = Directory.GetDirectories("Webspace");
                    foreach (string s in dirs)
                    {
                        //ersten Ordner aus Path entfernen (Webspace), da dieser nicht angegeben wird in der URL
                        string[] s_splitted = s.Split(new char[] { '\\' }, 2);
                        s_splitted[1] = HttpUtility.HtmlEncode(s_splitted[1]);

                        if (i % 2 == 0)
                            htmlText += "<tr class='style1'><td><a href='" + s_splitted[1] + "'>" + HttpUtility.HtmlEncode(Path.GetFileName(s)) + "</a></td><td>Directory</td></tr>";
                        else
                            htmlText += "<tr class='style2'><td><a href='" + s_splitted[1] + "'>" + HttpUtility.HtmlEncode(Path.GetFileName(s)) + "</a></td><td>Directory</td></tr>";
                        i++;
                    }

                    string[] files = Directory.GetFiles("Webspace");
                    foreach (string s in files)
                    {
                        //ersten Ordner aus Path entfernen (Webspace), da dieser nicht angegeben wird in der URL
                        string[] s_splitted = s.Split(new char[] { '\\' }, 2);
                        s_splitted[1] = HttpUtility.HtmlEncode(s_splitted[1]);

                        if (i % 2 == 0)
                            htmlText += "<tr class='style1'><td><a href='" + s_splitted[1] + "'>" + HttpUtility.HtmlEncode(Path.GetFileName(s)) + "</a></td><td>File</td></tr>";
                        else
                            htmlText += "<tr class='style2'><td><a href='" + s_splitted[1] + "'>" + HttpUtility.HtmlEncode(Path.GetFileName(s)) + "</a></td><td>File</td></tr>";
                        i++;
                    }

                    htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Path}", "/");
                    htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Content}", htmlText);

                    Response resp = new Response(req.getSocket());
                    resp.StatusCode = 200;
                    resp.StatusText = "OK";
                    resp.ContentType = "text/html";
                    //resp.Data = "<html><body><h3>Listing of Direcotry /</h3>" + htmlText + "</body></html>";
                    resp.Data = htmlOutput;
                    return resp;
                }
                else
                {
                    //Webspace Ordner existiert nicht! Sollte nicht eintreten da beim Start des Servers der Ordner erstellt wird. 
                    Response resp = new Response(req.getSocket());
                    resp.StatusCode = 500;
                    resp.StatusText = "Internal Server Error";
                    resp.ContentType = "text/html";
                    resp.Data = "<html><body><h1>Error 500: Internal Server Error</h1>" +
                        "<p>Der Webspace konnte nicht gefunden werden.</p></body></html>";
                    return resp;
                }
            }
            else
            {
                if(separatedBlocks.Length > 2)
                    separatedBlocks[1] = separatedBlocks[1] + "/" + separatedBlocks[2];

                separatedBlocks[1] = separatedBlocks[1].TrimEnd('/');
                Console.WriteLine("PathFromBrowser: " + separatedBlocks[1]);
                string pathWithoutWebspaceDir = separatedBlocks[1].Replace('/', '\\');
                Console.WriteLine("PathOnServer: " + pathWithoutWebspaceDir);
                string path = "Webspace" + '\\' + pathWithoutWebspaceDir;
                
                if (File.Exists(path))
                {
                    //Gueltiger Pfad zu einer Datei wurde eingegeben

                    Response resp = new Response(req.getSocket());
                    resp.SendFile = true;
                    resp.PathToFile = path;
                    resp.StatusCode = 200;
                    resp.StatusText = "OK";
                    return resp;
                    
                }
                else if (Directory.Exists(path))
                {
                    //Gueltiger Pfad zu einem Ordner wurde eingegeben

                    //Letzten Shlash entfernen falls vorhanden und letztes Verzeichnis aus Path entfernen
                    string parentPath = '/' + separatedBlocks[1];
                    parentPath = parentPath.TrimEnd('/');
                    parentPath = parentPath.Remove(parentPath.LastIndexOf('/')+1);

                    string htmlOutput = stringBuilder.ToString();
                    string htmlText = "<tr><th>Name</th><th>Type</th></tr>" +
                        "<tr class='style1'><td><a href='" + HttpUtility.HtmlEncode(parentPath) + "'><< Parent Directory</a></td><td/></tr>";

                    int i = 1;
                    string[] dirs = Directory.GetDirectories(path);
                    foreach (string s in dirs)
                    {
                        //ersten Ordner aus Path entfernen (Webspace), da dieser nicht angegeben wird in der URL
                        string[] s_splitted = s.Split(new char[] { '\\' }, 2);
                        //zurueck nach Browserformat umwandeln
                        s_splitted[1] = s_splitted[1].Replace('\\', '/');
                        s_splitted[1] = HttpUtility.HtmlEncode(s_splitted[1]);

                        if (i % 2 == 0)
                            htmlText += "<tr class='style1'><td><a href='/" + s_splitted[1] + "'>" + HttpUtility.HtmlEncode(Path.GetFileName(s)) + "</a></td><td>Directory</td></tr>";
                        else
                            htmlText += "<tr class='style2'><td><a href='/" + s_splitted[1] + "'>" + HttpUtility.HtmlEncode(Path.GetFileName(s)) + "</a></td><td>Directory</td></tr>";
                        i++;
                    }
                    string[] files = Directory.GetFiles(path);
                    foreach (string s in files)
                    {
                        //ersten Ordner aus Path entfernen (Webspace), da dieser nicht angegeben wird in der URL
                        string[] s_splitted = s.Split(new char[] { '\\' }, 2);
                        //zurueck nach Browserformat umwandeln
                        s_splitted[1] = s_splitted[1].Replace('\\', '/');
                        s_splitted[1] = HttpUtility.HtmlEncode(s_splitted[1]);

                        if (i % 2 == 0)
                            htmlText += "<tr class='style1'><td><a href='/" + s_splitted[1] + "'>" + HttpUtility.HtmlEncode(Path.GetFileName(s)) + "</a></td><td>File</td></tr>";
                        else
                            htmlText += "<tr class='style2'><td><a href='/" + s_splitted[1] + "'>" + HttpUtility.HtmlEncode(Path.GetFileName(s)) + "</a></td><td>File</td></tr>";
                        i++;
                    }

                    htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Path}", "/" + HttpUtility.HtmlEncode(separatedBlocks[1]));
                    htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Content}", htmlText);

                    Response resp = new Response(req.getSocket());
                    resp.StatusCode = 200;
                    resp.StatusText = "OK";
                    resp.ContentType = "text/html";
                    //resp.Data = "<html><body>" + "<h3>Listing of Directory /" + HttpUtility.HtmlEncode(separatedBlocks[1]) + "</h3>" + htmlText + "</body></html>";
                    resp.Data = htmlOutput;
                    return resp;
                }
                else
                {
                    //Pfad zu Ordner oder Datei existiert nicht
                    Response resp = new Response(req.getSocket());
                    resp.StatusCode = 404;
                    resp.StatusText = "Not Found";
                    resp.ContentType = "text/html";
                    resp.Data = "<html><body><h1>Error 404 - Not Found</h1></body></html>";
                    return resp;
                }
            }
            
        }
    }
}
